package testcase;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.Hashtable;
import java.util.NoSuchElementException;

import org.junit.Test;

import satir.SatirTherapy;

import satir.command.Command;

import junit.framework.TestCase;

public class In_Lv_2_SatirTherapy_1 extends TestCase {

	public class CommandStub implements Command {
		CommandStub() {
		}

		public void execute() {
			System.out.println("Command executed!");
		}

	};
	
	// Force each Scanner can only read 1 word
	class TestPurposeByteArrayInputStream extends ByteArrayInputStream{
		
		private Hashtable<String, Integer> called;

		public TestPurposeByteArrayInputStream(byte[] buf) {
			super(buf);
			called = new Hashtable<String, Integer>();
		}
		
		// Force read only 1 word to the buffer
		public int read(byte[] b,
                int off,
                int len){
			try{
		         throw new Exception("Who called me?");
			} catch (Exception e) {
				String caller = e.getStackTrace()[8].getClassName() + "." + e.getStackTrace()[8].getMethodName() + "()"+ " hash" + e.getStackTrace()[8].hashCode();
				if(!called.containsKey(caller)){
					called.put(caller, 1);
				}else{
					//System.err.println(caller + " is called");
					return -1;
				}
		    }
			skipWriteSpace();
			len = getNextWordLength();
			int val = super.read(b, off, len);
			String s = new String(b);
			//System.err.println("Called read. Word["+s+"]");
			return val;
		}
		
		private int getNextWordLength(){
			int index = 1;
			while(index+pos < count && buf[index+pos] != ' '){
				index++;
			}
			return index;
		}
		
		private void skipWriteSpace(){
			int len = 0;
			while(len+pos < count && buf[len+pos] == ' '){
				len++;
			}
			skip(len);
		}	
	}
	
	@Test
	public void testStartGame() {
		String input = "1 2 Torrey";		
		ByteArrayInputStream in = new TestPurposeByteArrayInputStream(input.getBytes());
		System.setIn(in);
		
		final ByteArrayOutputStream systemOut = new ByteArrayOutputStream();
		PrintStream original = System.out;
		System.setOut(new PrintStream(systemOut)); // Start store the output
													// here
		try {
			SatirTherapy.main(new String[] {});
		} catch (NoSuchElementException e) {
		}
		System.setOut(original); // Store the output unit here

		String actualResult = systemOut.toString();

		// Check the output of SatirTherapy.startSatirTherapy() it self
		String expectedResult = "Hello" + "\r\n"
				+ "Please indicate your selection." + "\r\n" + "[1] Play game."
				+ "\r\n" + "[2] Analyze specific user." + "\r\n" + "[3] Exit"
				+ "\r\n";

		// Check the output of PlaySatirGameCmd.execute() called by
		// SatirTherapy.startSatirTherapy()
		expectedResult += "Input the number of players:(2-6)" + "\r\n";
		expectedResult += "There are 2 players" + "\r\n"
				+ "Player 1 please input your name:" + "\r\n";
		
		expectedResult += "Hi [Torrey]" + "\r\n"
					    + "Player 2 please input your name:" + "\r\n";

		assertEquals(expectedResult, actualResult);
	}
}
